package pl.edu.agh.gt.ga;

import java.io.File;
import java.io.IOException;
import java.util.Date;
import java.util.List;

import org.apache.log4j.Level;
import org.apache.log4j.Logger;

import pl.edu.agh.gt.data.DataProvider;
import pl.edu.agh.gt.data.RatesHistory;
import pl.edu.agh.gt.ga.greedy.CrossbreedImlpl;
import pl.edu.agh.gt.ga.greedy.FitnessFunctionImpl;
import pl.edu.agh.gt.ga.greedy.InitializerImpl;
import pl.edu.agh.gt.ga.greedy.MutationImpl;

public class EA implements PopulationListener {

	private final static Logger log = Logger.getLogger(EA.class);
	private static long start;
	private static long stop;
	
	Parameters params;
	Population population;
	FitnessFunction fitness;
	MutationOperator mutation;
	CrossbreedOperator xbreed;
	Initializer initializer;
	
	public EA () throws IOException {
		// preare params
		params = new Parameters();
		
		// prepare stock
		@SuppressWarnings("deprecation")
		Date start = new Date(2005 - 1900, 3, 15); // 7 // 11 // 7

		@SuppressWarnings("deprecation")
		Date end = new Date(2005 - 1900, 8, 15); // 18 downup // 23 rosnacy // 11 malejacy

		log.info("Using stock period " + start + " to " + end);

		RatesHistory rates = DataProvider.readData(
				new File("src/main/resources/EURUSD_hour.csv")).getPeriod(
				start, end);

		fitness = new FitnessFunctionImpl(rates);
		mutation = new MutationImpl();
		xbreed = new CrossbreedImlpl();
		initializer = new InitializerImpl();

		// create population
		population = new Population(params, initializer,
				fitness, mutation, xbreed);
		population.setListener(this);	
	}
	
	public void execute () throws Exception {
		// run ...
		population.initializePopulation();
		population.evolvePopulation();
	}
	
	@Override
	public void onIterationDone(Population p) throws IOException {
		if(p.getIteration() % 10 == 0 )
			p.diag();		
	}

	@Override
	public void onEvolutionFinished(Population p) throws Exception {
		// present results
		// stock performance for best ind's
		List<Individual> bestInds = p.getNBestIndividuals(3);
		for(Individual i : bestInds)
			((FitnessFunctionImpl)fitness).showGenotypeTradingComparedToBuyAndHold(i.genotype);
		
	}

	public static void main(String[] args) {

		try {
			Logger.getLogger("pl.edu.agh.gt.ea").setLevel(Level.INFO);
			Logger.getLogger("pl.edu.agh.gt.strategy").setLevel(Level.WARN);
			Logger.getLogger("pl.edu.agh.gt.stock").setLevel(Level.WARN);
			
			tic();
			
			new EA().execute();
			
			tac();
			
		} catch (Exception e) {
			log.error(e);
		}

	}

	private static void tac() {
		stop = System.currentTimeMillis();
		log.info("Time elapsed [s]: "+(stop - start)/1000.0f);
	}

	private static void tic() {
		start = System.currentTimeMillis();
	}

	@Override
	public void onPopulationInitialized(Population p) {
		
	}

	

}
